package il.ac.tau.arielgue.outxing.agents;

import il.ac.tau.arielgue.outxing.utils.Params;
import proevolution.agents.Organism;
import repast.simphony.annotate.AgentAnnot;
import repast.simphony.random.RandomHelper;
import simphony.util.messages.MessageCenter;

/**
 * 
 * @author arielg
 * 
 */
@AgentAnnot(displayName = "FAOOrganism")
public class FAOOrganism extends OutXingOrganism {
	private static final long serialVersionUID = -1985607518497848356L;
	protected static final MessageCenter logger = MessageCenter
			.getMessageCenter(FAOOrganism.class);

	public FAOOrganism() {
		super();
	}

	public FAOOrganism(OutXingOrganism organism) {
		super(organism);
	}

	public FAOOrganism(FAOOrganism organism) {
		super(organism);
	}

	/**
	 * returns the FAO outcrossing tendency as a function of fitness: it is
	 * sigmoid [0,1]->[0,1] (maxX was chosen to be 10, for which
	 * 1/(1+exp(-10))=0.99995...) offset in Locust outcrossing simulation (the
	 * motivation for Xingulation) is usually "density" or "feedback", and
	 * determines around which point the sigmoid should be symmetric when
	 * offset=1, the symmetric point is midX (usually 0.5), i.e. there's no
	 * influence of either low or high "density", or there's no influence of the
	 * "feedback" (i.e. - all are already outcrossing).
	 */
	@Override
	public double getOutXingTendency(double slope, double maxX, double midX,
			double offset) {
		double tendency = Params.getMeanOutXingFraction();
		if ((getOutXingModifier() == HOMOZYGOT_BB)
				|| ((getOutXingModifier() == HETEROZYGOT_AB || getOutXingModifier() == HETEROZYGOT_BA) && (RandomHelper
						.nextDouble() < 0.5))) {
			// DEBUGGING
			// tendency = 1 - 1 / (1 + Math.exp(-2 * slope * maxX - ????????
			// * (getFitness() - midX * offset))); ????? below something i
			// understand better - Ariel
			// DEBUGGING
			tendency = 1 / (1 + Math.exp(-slope * maxX
					* ((((1-getFitness()) / midX) * offset) - 1)));
		}
		// logger.debug("Tendency is " + tendency);
		return tendency;
	}

	/**
	 * returns 1 for FF or 0 for FO and OF.
	 */
	public int isHomozygot() {
		if (getOutXingModifier() == HOMOZYGOT_BB)
			return 1;
		else
			return 0;
	}

	@Override
	protected Organism spawn() {
		return new FAOOrganism(this);
	}

	public static OutXingOrganism create(OutXingOrganism parent) {
		return new FAOOrganism(parent);
	}
}
